package cn.tedu.charging.order.service.Impl;

import cn.tedu.charging.common.pojo.Param.GunStatusUpdateParam;
import cn.tedu.charging.common.pojo.VO.StationInfoVO;
import cn.tedu.charging.common.pojo.VO.UserInfoVO;
import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.common.ChargingConstants;
import cn.tedu.charging.order.common.GunStatusConstants;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.mqtt.MqttProducer;
import cn.tedu.charging.order.pojo.Dto.ChargingDto;
import cn.tedu.charging.order.pojo.Param.OrderCreateParam;
import cn.tedu.charging.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import cn.tedu.charging.common.pojo.JsonResult;

import java.util.Random;

import cn.tedu.charging.order.common.MqttConstants;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 生成订单号
     * 唯一性
     * 1、UUID随机且唯一
     *
     * 分布式id生成器
     * 雪花算法
     * 美团leaf算法
     *
     *
     * MVP
     * 100000+随机数+时间戳
     * */
    @Override
    public String createOrder(OrderCreateParam orderCreateParam) {
        log.debug("创建订单-入参{}",orderCreateParam);
        log.debug("创建订单-生成订单号");
        String orderNo =getOrderNo();
        log.debug("创建订单-生成订单号:{}",orderNo);
        log.debug("创建订单-获取用户信息");
        Integer userId = orderCreateParam.getUserId();
        log.debug("创建订单-获取用户信息:入参：{}",userId);
        UserInfoVO userInfoVO = getUserInfoByOpenFeign(userId);
        log.debug("创建订单-获取用户信息:入参：{},出参：{}",userId,userInfoVO);
        log.debug("创建订单-获取场站信息-入参:{}",orderCreateParam.getGunId());
        StationInfoVO stationInfoVO = getStationInfo(orderCreateParam.getGunId());
        log.debug("创建订单-获取场站信息-入参：{},出参:{}",orderCreateParam.getGunId(),stationInfoVO);
        //修改枪状态为使用中
        log.debug("创建订单-修改枪状态-入参:{},{}",orderCreateParam.getGunId(), GunStatusConstants.GUN_STATUS_USING);
        updateGunStatus(orderCreateParam.getGunId(),GunStatusConstants.GUN_STATUS_USING);
        startCharging(orderNo, orderCreateParam.getPileId(), orderCreateParam.getGunId());
        return orderNo;
    }

    @Autowired
    private MqttProducer mqttProducer;
    private void startCharging(String orderNo, Integer pileId,Integer gunId){
        //topic设计
        //枪纬度 枪id
        //桩纬度 桩id
        String topic = MqttConstants.TOPIC_START_CHARGE_PREFIX+pileId;
        //消息设计
        //开始充电指令
        //参数 订单信息唯一标识 订单号 设备信息 枪id 告诉桩 用哪个枪 目标 给哪个用户 哪个订单 开始充电
        ChargingDto chargingDto = new ChargingDto();
        chargingDto.setOrderNo(orderNo);
        chargingDto.setPileId(pileId);
        chargingDto.setGunId(gunId);
        chargingDto.setMsg(ChargingConstants.START_CHARGE);
        log.debug("发送充电指令到设备-Topic:{},消息:{}",topic, chargingDto);
        //java对象转换为json字符串
        //消息的序列化 Springboot以及帮我们做好了

        String message = JsonUtils.toJson(chargingDto);
        log.debug("发送充电指令到设备-Topic:{}，消息对象{},消息:{}",topic, chargingDto, message);
        Boolean success = mqttProducer.send(topic, message);
        log.debug("发送充电指令到设备-Topic:{},消息:{},发送结果:{}",topic, message, success);
    }

    @Autowired
    private DeviceClient deviceClient;
    public Boolean updateGunStatus(Integer gunId,Integer status){
        log.debug("更新枪状态-入参:{},{}",gunId,status);
        GunStatusUpdateParam gunStatusUpdateParam = new GunStatusUpdateParam();
        gunStatusUpdateParam.setGunId(gunId);
        gunStatusUpdateParam.setStatus(status);
        JsonResult<Boolean> result= deviceClient.updateGunInfo(gunStatusUpdateParam);
        if (result!=null){
            return result.getData();
        }
        return false;
    }

    private StationInfoVO getStationInfo(Integer gunId){
        JsonResult<StationInfoVO> stationInfo = deviceClient.getStationInfo(gunId);
        if (stationInfo != null) {
            return stationInfo.getData();
        }
        return null;
    }

    private UserInfoVO getUserInfo(Integer userId){
        String url = getRandomUrl();
        ParameterizedTypeReference<JsonResult<UserInfoVO>>
                repType =
                new ParameterizedTypeReference<JsonResult<UserInfoVO>>() {};
        ResponseEntity<JsonResult<UserInfoVO>> entity=restTemplate.exchange(url, HttpMethod.GET,null,repType,userId);
        JsonResult<UserInfoVO> body = entity.getBody();
        return body.getData();
    }
    @Autowired
    private UserClient userClient;
    private UserInfoVO getUserInfoByOpenFeign(Integer userId){
        JsonResult<UserInfoVO> userInfo=userClient.getUserInfo(userId);
        UserInfoVO data = userInfo.getData();
        return data;

    }


    private String getRandomUrl(){
        String url = "http://localhost:7070/user/info/{1}";
        String url1 = "http://localhost:7071/user/info/{1}";
        String url2 = "http://localhost:7072/user/info/{1}";
        String[] urls = new String[]{url,url1,url2};
        Random random = new Random();
        int rIndex = random.nextInt(urls.length);
        return urls[rIndex];
    }

    private String getOrderNo(){
        //前缀
        String start = "100000";
        Random random = new Random();
        //生成10000之间的随机数
        int num = random.nextInt(10000);
        //3
        long now = System.currentTimeMillis();
        return start+'_'+num+'_'+now;
    }

}
